using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace Universe.CrossIO.Test
{
    internal delegate void WriteSource(Stream stream, int length);

    static class MyEnvironment
    {
        public static readonly int[] Sizes = new int[] { 0, 1, 2, 3, 1024, 1024 * 1024 };

        public static string ClassPath
        {
            get
            {
                string[] rel = new string[]
                    {
                        @"..\..\..\cldctest\dist\cldctest.jar",
                        @"..\..\..\universe\dist\universe.jar"
                    };

                StringBuilder ret = new StringBuilder();
                foreach (string s in rel)
                {
                    string p = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, s));
                    ret.Append(ret.Length == 0 ? "" : ";").Append(p);
                }

                return ret.ToString();
            }
        }

        public static  readonly WriteSource[] SourceWriters =
            new WriteSource[]
                {
                    MyEnvironment.WriteRandom,
                    MyEnvironment.WriteRepeated
                };



        public static void WriteRandom(Stream stream, int length)
        {
            Random rand = new Random(length);
            using(BufferedStream bf = new BufferedStream(stream, 8192))
            {
                for(int i=0; i<length; i++)
                    bf.WriteByte((byte) rand.Next(0, 255));
            }
        }

        public static void WriteRepeated(Stream stream, int length)
        {
            using (BufferedStream bf = new BufferedStream(stream, 8192))
            {
                for (int i = 0; i < length; i++)
                    bf.WriteByte((byte) ((i / 5) & 0xFF));
            }
        }

        public static bool ComparePlainAndPlain(string plain1, string plain2)
        {
            using (FileStream p1 = new FileStream(plain1, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (FileStream p2 = new FileStream(plain2, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (BufferedStream bp1 = new BufferedStream(p1, 8192))
            using (BufferedStream bp2 = new BufferedStream(p2, 8192))
            {
                int count = 0;
                while (true)
                {
                    int next1 = bp1.ReadByte();
                    if (next1 < 0)
                        break;

                    int next2 = bp2.ReadByte();
                    if (next2 < 0)
                        return false;

                    if (next1 != next2)
                        return false;

                    count++;
                }

                if (count != p2.Length)
                    throw new InvalidOperationException("RE is same as plain, however RE size is " + p2.Length);

                return true;
            }
        }

        public static bool ComparePlainAndGZipped(string plain, string gzipped)
        {
            using (FileStream pl = new FileStream(plain, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (BufferedStream bpl = new BufferedStream(pl, 8192))
            using (FileStream target = new FileStream(gzipped, FileMode.Open, FileAccess.Read, FileShare.Read))
            using (GZipStream unpack = new GZipStream(target, CompressionMode.Decompress))
            using (BufferedStream bunpack = new BufferedStream(unpack, 8192))
            {
                int count = 0;
                while (true)
                {
                    int next1 = bunpack.ReadByte();
                    if (next1 < 0)
                        break;

                    int next2 = bpl.ReadByte();
                    if (next2 < 0)
                        return false;

                    if (next1 != next2)
                        return false;

                    count++;
                }

                if (count != pl.Length)
                    throw new InvalidOperationException("GZipped is same, however plain size is " + plain.Length);

                return true;
            }
        }

        public static void Copy(Stream source, Stream target)
        {
            byte[] buffer = new byte[32768];
            while(true)
            {
                int n = source.Read(buffer, 0, buffer.Length);
                if (n <= 0)
                    break;

                target.Write(buffer, 0, n);
            }
        }

        public static String HexDecode(string raw)
        {
            MemoryStream mem = new MemoryStream();
            for(int i=0; i<raw.Length; i+= 2)
                mem.WriteByte((byte) int.Parse(raw.Substring(i,2), NumberStyles.HexNumber));

            BinaryReader reader = new BinaryReader(new MemoryStream(mem.ToArray()));
            return CrossIO.Reader.JReadString(reader);
        }
    }
}
